import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'models/paint_layer.dart';
import 'widgets/tool_box.dart';

class PainterPage extends StatefulWidget {
  PainterPageState createState() => PainterPageState();
}

class PainterPageState extends State<PainterPage> {
  Color color = Colors.black;
  StrokeCap stroke = StrokeCap.round;
  double width = 5.0;

  List<PaintLayer> layers = [];
  int currentLayer = 0;
  bool layerNext = true;

  List<Color> colors = [Colors.black, Colors.white] + Colors.primaries;
  List<double> sizes = [1, 2, 3, 5, 10, 15, 20, 50];

  @override
  void initState() {
    super.initState();
    newLayer();
  }

  void takePhoto() {}

  void undo() {
    if (currentLayer > 0) {
      setState(() {
        currentLayer--;
        layerNext = true;
      });
    }
  }

  void redo() {
    if (currentLayer < layers.length - 1) {
      setState(() {
        currentLayer++;
        layerNext = true;
      });
    }
  }

  void erase() {}

  void clear() {
    layers.clear();
    newLayer();
    setState(() {});
  }

  String getStrokeText(StrokeCap stroke) {
    switch (stroke) {
      case StrokeCap.butt:
        return '无';
      case StrokeCap.round:
        return '圆形';
      case StrokeCap.square:
        return '方形';
      default:
        return stroke.toString().split('.')[1];
    }
  }

  Widget toolBar() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        IconButton(
          onPressed: () {
            takePhoto();
          },
          icon: Icon(CupertinoIcons.camera),
        ),
        Row(
          children: [
            ToolBox(child: Text('背景')),
            SizedBox(
              width: 10,
            ),
            DropdownButton<Color>(
              value: color,
              hint: Icon(
                Icons.check_circle,
                color: color,
              ),
              icon: const Icon(CupertinoIcons.chevron_down),
              iconSize: 24,
              elevation: 16,
              style: const TextStyle(color: Colors.deepPurple),
              underline: Container(
                height: 1,
                color: Colors.deepPurpleAccent,
              ),
              onChanged: (Color? newValue) {
                setState(() {
                  color = newValue!;
                });
              },
              items: colors.map<DropdownMenuItem<Color>>((Color value) {
                return DropdownMenuItem<Color>(
                  value: value,
                  child: Icon(
                    value == color ? Icons.check_circle : Icons.circle,
                    color: value,
                  ),
                );
              }).toList(),
            ),
            SizedBox(
              width: 10,
            ),
            DropdownButton<double>(
              value: width,
              hint: Text('粗细 $width'),
              icon: const Icon(CupertinoIcons.chevron_down),
              iconSize: 24,
              elevation: 16,
              style: const TextStyle(color: Colors.deepPurple),
              underline: Container(
                height: 1,
                color: Colors.deepPurpleAccent,
              ),
              onChanged: (double? newValue) {
                setState(() {
                  width = newValue!;
                });
              },
              items: sizes.map<DropdownMenuItem<double>>((double value) {
                return DropdownMenuItem<double>(
                  value: value,
                  child: Text('粗细 $value'),
                );
              }).toList(),
            ),
            SizedBox(
              width: 10,
            ),
            DropdownButton<StrokeCap>(
              value: stroke,
              hint: Text('笔触 ${getStrokeText(stroke)}'),
              icon: const Icon(CupertinoIcons.chevron_down),
              iconSize: 24,
              elevation: 16,
              style: const TextStyle(color: Colors.deepPurple),
              underline: Container(
                height: 1,
                color: Colors.deepPurpleAccent,
              ),
              onChanged: (StrokeCap? newValue) {
                setState(() {
                  stroke = newValue!;
                });
              },
              items: StrokeCap.values
                  .map<DropdownMenuItem<StrokeCap>>((StrokeCap value) {
                return DropdownMenuItem<StrokeCap>(
                  value: value,
                  child: Text('笔触 ${getStrokeText(value)}'),
                );
              }).toList(),
            ),
            IconButton(
              onPressed: () {
                clear();
              },
              icon: Icon(CupertinoIcons.bag),
            ),
            IconButton(
              onPressed: () {
                erase();
              },
              icon: Icon(CupertinoIcons.bandage),
            ),
          ],
        ),
        Row(
          children: [
            IconButton(
              onPressed: () {
                undo();
              },
              icon: Icon(CupertinoIcons.arrow_turn_up_left),
            ),
            IconButton(
              onPressed: () {
                redo();
              },
              icon: Icon(CupertinoIcons.arrow_turn_up_right),
            ),
          ],
        )
      ],
    );
  }

  void newLayer() {
    layers.add(PaintLayer(color: color, stroke: stroke, width: width));
    currentLayer = layers.length - 1;
  }

  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.topCenter,
      children: [
        GestureDetector(
          onPanUpdate: (DragUpdateDetails details) {
            if (currentLayer < layers.length - 1) {
              layers = layers.sublist(0, currentLayer + 1);
            }
            if (layerNext) {
              layerNext = false;
              newLayer();
            }
            setState(() {
              layers[currentLayer].addPoint(details.localPosition);
            });
          },
          onPanEnd: (DragEndDetails details) {
            if (layers[currentLayer].hasPoint) {
              layerNext = true;
            }
          },
          child: Stack(
            alignment: Alignment.center,
            children: layers
                .sublist(0, currentLayer + 1)
                .map<CustomPaint>(
                  (layer) => CustomPaint(
                    painter: SignaturePainter(layer),
                    size: Size.infinite,
                  ),
                )
                .toList(),
          ),
        ),
        toolBar(),
      ],
    );
  }
}

class SignaturePainter extends CustomPainter {
  SignaturePainter(this.layer);

  final PaintLayer layer;
  void paint(Canvas canvas, Size size) {
    layer.paint(canvas);
  }

  bool shouldRepaint(SignaturePainter other) => layer.shouldPaint;
}
